package me.yricky.cbor

@Target(AnnotationTarget.CLASS)
annotation class UnsupportedCBORItem

sealed class CBORItem

object CBORTrue:CBORItem()
object CBORFalse:CBORItem()
object CBORNull:CBORItem()
object CBORUndefined:CBORItem()
class CBORNum(val value:Long):CBORItem()
fun CBORNum(value:Number) = CBORNum(value.toLong())

@UnsupportedCBORItem
class CBORFloat(val value:Float):CBORItem()

@UnsupportedCBORItem
class CBORDouble(val value:Double):CBORItem()
class CBORString(val value: String):CBORItem()
class CBORArray(val value: List<CBORItem>):CBORItem()
class CBORByteArray(val value: ByteArray):CBORItem()
class CBORKv(val value: List<Pair<CBORItem,CBORItem>>):CBORItem()

val CBORItem.str get():String = when(this){
    is CBORTrue-> "true"
    is CBORFalse -> "false"
    is CBORNull -> "null"
    is CBORUndefined -> "undefined"
    is CBORNum -> "$value"
    is CBORFloat -> "$value"
    is CBORDouble -> "$value"
    is CBORString -> "\"$value\""
    is CBORArray -> StringBuilder().also {
        it.append("[")
        value.forEachIndexed { index, cborItem ->
            it.append(cborItem.str)
            if(index != value.size-1){
                it.append(",")
            }
        }
        it.append("]")
    }.toString()
    is CBORByteArray -> "\"${value.hexString()}\""
    is CBORKv -> StringBuilder().also {
        it.append("{")
        value.asIterable().forEachIndexed { index, pair ->
            it.append(pair.first.str)
            it.append(":")
            it.append(pair.second.str)
            if(index != value.size-1){
                it.append(",")
            }
        }
        it.append("}")
    }.toString()
}